#ifndef __CAEVENTH__
#define __CAEVENTH__

#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <assert.h>
#include <unistd.h>
#include <pthread.h>
#include "calist.h"
#include "catimer.h"
#include "cathread.h"

#define MAX_GET_EVENTS 10

/*
enum {
	CAMSG_ES_EXIT=999,
	CAMSG_USER = 1000,
	
};*/

#define EM_TIMER 1
#define EM_INIT 2
#define EM_CLOSE 3
#define EM_SOCKET 4
#define EM_READY 5
#define EM_EXIT 999
#define EM_USER 1000


struct es_t;
struct evt_t;

typedef int (*EVTMSG_PROC)(es_t* psys, uint16_t msg, uint16_t p1, uint32_t p2);
typedef void (*EVTIPC_PROC)(es_t* psys, int fd);

typedef struct es_t
{
	int epfd;
	
	int exit_flag;
	int opened;
	// extra ipc
	int lfd, rfd;
	evt_t* pevt_ipcext;
	EVTIPC_PROC ipc_proc;
	
	lklist* pevtlist;
	int evt_count;

	int handle_seed;
	//catimer_t timer_res[10];

	// es timer list
	int timer_cnt;
	lklist* timer_list;

	// time
	struct timeval tm;
	
	// msg proc
	int event_fd;
	EVTMSG_PROC msg_proc;
	evt_t* pevt_msg;
	pthread_cond_t msg_sig;
	pthread_mutex_t msg_sync_mutex;
	union {
		void* mresult_ptr;
		int mresult;
	};

	uint16_t init_p1;
	uint32_t init_p2;
	void *user;

	// for debugging
	int evt_alloc_cnt;
	int timer_alloc_cnt;

	
} es_t;

typedef struct evt_t
{
	lklist list;
	int fd;
	void* user;
	int wevents;
	es_t *psys;
	void (*evtcb)(evt_t* pevt, int fd, int events);
	int handle;
} evt_t;

typedef void (*EVENTCB)(evt_t* pevt, int fd, int events);

typedef struct evtmsg_t
{
	uint16_t msgid;
	uint16_t p1;
	uint32_t p2;
} evtmsg_t;

//evt_t* alloc_evt(es_t* psys);
//void free_evt(evt_t* pevt);

int es_open(es_t* psys);
void es_close(es_t* psys);

int es_main(es_t* psys);
void es_ready(es_t* psys);
void es_exit(es_t* psys);

evt_t* es_reg(es_t* psys, int fd, uint32_t events, EVENTCB cb, void* user);
void es_dereg(es_t* psys, evt_t* pevt);
int es_change(evt_t* pevt, uint32_t event);
int es_alloc_user(es_t* psys, int size);
void es_set_init_para(es_t* psys, uint16_t p1, uint32_t p2);
void es_register_msgproc(es_t* psys, EVTMSG_PROC proc);
void es_postmsg(es_t* psys, uint16_t msg, uint16_t p1, uint32_t p2);
int es_sendmsg(es_t* psys, uint16_t msgid, uint16_t p1, uint32_t p2, int *presult=NULL);
unsigned int es_mtime(es_t *psys);

void es_set_msg_result(es_t* psys, int result);
void setNonBlockMode(int fd);


#endif
